home *** CD-ROM | disk | FTP | other *** search
/ Complete Linux / Complete Linux.iso / docs / apps / database / postgres / postgre4.z / postgre4 / src / rules / prs2 / prs2bkwd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-27  |  19.8 KB  |  692 lines

  1. /*===================================================================
  2.  *
  3.  * FILE:
  4.  *   prs2bkwd.c
  5.  *
  6.  * IDENTIFICATION:
  7.  *   $Header: /private/postgres/src/rules/prs2/RCS/prs2bkwd.c,v 1.9 1992/07/14 00:22:42 mer Exp $
  8.  *
  9.  * DESCRIPTION:
  10.  *   These are routines that can be used to implement the
  11.  *   'backward' chaining rules, i.e. rules that update the
  12.  *   current tuple. Examples of these rules are:
  13.  *    on retrieve to EMP.salary where EMP.name = "mike"
  14.  *    do instead retrieve (salary=1000)
  15.  * or
  16.  *    on append to EMP where EMP.age<25
  17.  *    do replace CURRENT(salary=2000)
  18.  *
  19.  *
  20.  * There are two main routines in this module:
  21.  * `prs2ActivateBackwardChainingRules' and `prs2ActivateForwardChainingRules'
  22.  *
  23.  * At any point the rule manager has 1 or 2 tuples to consider. The 'old'
  24.  * tuple and/or the 'new' tuple.
  25.  * In the case of a 'delete' or 'retrieve' event, it only has an 'old'
  26.  * tuple. In the case of a 'append' it only has a 'new' tuple, and finally
  27.  * in the case of a 'replace' it has both a 'new' and an 'old' tuple.
  28.  * 
  29.  * Any of these events can activate some rules. These rules can
  30.  * either be 'backward chaining' rules (i.e. rules that have
  31.  * a lock of type 'LockTypeXXXWrite' where XXX is the appropriate event)
  32.  * or `forward chanining' (with a 'LockTypeXXXAction' lock).
  33.  * In the first case, we must call 'prs2ActivateBackwardChainingRules' for
  34.  * every attribute that has the 'LockTypeXXXWrite' lock.
  35.  * This routine, finds these rules (if they exist) checks their
  36.  * qualification and if true it activates them, retrieves the value
  37.  * calculated by the rule and puts it in the tuple.
  38.  * 
  39.  * Explanation of parameters:
  40.  * Most fo them are common in both 'prs2ActivateBackwardChainingRules'
  41.  * and 'prs2ActivateForwardChainingRules'.
  42.  *
  43.  *   prs2EStateInfo: information (usually stored in the EState node)
  44.  *       needed for loop detection.
  45.  *   relation: the relation both 'old' & 'new' tuples belong to.
  46.  *   attributeNumber: the number of the attribute that is 'touched'
  47.  *       by the event.
  48.  *   oldOrNewTuple: is this an attribute of the 'old' or of the
  49.  *       'new' tuple?
  50.  *   oldTupleOid: the oid of the 'old' tuple.
  51.  *   oldAttributeValues: an array containing the values of the
  52.  *       'old' tuple, plus some other info.
  53.  *   oldTupleLocks: the rule locks of the old tuple.
  54.  *   oldTupleLockType: the lock type (one of the 'LockTypeXXXWrite'
  55.  *       locks that should be used to calculate the values of the
  56.  *       'old' tuple's attributes. See discussion below.
  57.  *   newTupleOid,
  58.  *   newAttributeValues,
  59.  *   newTupleLocks,
  60.  *   newTupleLockType: similar to 'old' tuple stuff...
  61.  *
  62.  * The following arguments appear only in 'prs2ActivateForwardChainingRules'
  63.  *   eventLockType: The lock type that a forward chaining rule must
  64.  *        have in the specified attribute in order to be activated.
  65.  *    
  66.  * Both routines, might call 'prs2CalculateAttributesOfParamNodes'
  67.  * (which in turn might also call prs2ActivateBackwardChainingRules')
  68.  * The reason is that a rule plan might have some parameters (the NEW
  69.  * & OLD stuff...), in which case we have first to calculate the
  70.  * correct values for the correpsonding attributes (of either the
  71.  * 'new' or 'old' tuple, depending on the type of paramterer)
  72.  * before we execute the plan.
  73.  *
  74.  * 'prs2ActivateBackwardChainingRules' is (directly) called by the PRS2
  75.  * routines that handle 'retrieve', 'append' and 'replace' events.
  76.  * It is called to activate all the backward chaining rules that
  77.  * might affect the value of a certain attribute.
  78.  * 
  79.  * In the 'retrieve' case, we only have an 'old' tuple, so all the
  80.  * info about the 'new' tuple is ignored. The lock type that is 
  81.  * used is 'LockTypeRetrieveWrite'.
  82.  * In the case of 'append' event, we only have a new tuple, and
  83.  * the lock type is 'LockTypeAppendWrite'
  84.  * Finally in the case of replace, we have both a 'new' & 'old'
  85.  * tuple, however we (directly) call 'prs2ActivateBackwardChainingRules'
  86.  * only for the new tuple and the lock type is 'LockTypeReplaceWrite'.
  87.  *
  88.  * 'prs2ActivateForwardChainingRules' is called by
  89.  * the prs2 routines thath handle 'retrieve', 'delete', 'append'
  90.  * and 'replace' events.
  91.  *
  92.  * In the 'retrieve' case, we only have a 'old' tuple, the
  93.  * `eventTypeLock' is 'LockTypeRetrieveAction' and the 'oldTupleLockType'
  94.  * is 'LockTypeRetrieveWrite'
  95.  *
  96.  * In the 'delete' case, we only have an 'old' tuple, the 
  97.  * `eventTypeLock' is 'LockTypeDeleteAction' and the 'oldTupleLockType'
  98.  * is 'LockTypeRetrieveWrite'
  99.  * 
  100.  * In the 'append' case, we only have a 'new' tuple, the 
  101.  * `eventTypeLock' is 'LockTypeAppendAction' and the 'newTupleLockType'
  102.  * is 'LockTypeAppendWrite'
  103.  * 
  104.  * In the 'replace' case, we have both an 'old' & a 'new' tuple, the 
  105.  * `eventTypeLock' is 'LockTypeReplaceAction', the 'oldTupleLockType'
  106.  * is 'LockTypeRetrieveWrite' and the 'newTupleLockType' is
  107.  * 'LockTypeReplaceWrite'
  108.  *
  109.  *===================================================================
  110.  */
  111.  
  112. #include "tmp/c.h"
  113. #include "utils/log.h"
  114. #include "rules/prs2.h"
  115.  
  116. /*-------------------------------------------------------------------
  117.  * prs2ActivateBackwardChainingRules()
  118.  *
  119.  */
  120. void
  121. prs2ActivateBackwardChainingRules(
  122.         prs2EStateInfo,
  123.         explainRelation,
  124.         relation,
  125.         attributeNumber,
  126.         oldOrNewTuple,
  127.         oldTupleOid,
  128.         oldAttributeValues,
  129.         oldTupleLocks,
  130.         oldTupleLockType,
  131.         newTupleOid,
  132.         newAttributeValues,
  133.         newTupleLocks,
  134.         newTupleLockType,
  135.         attributeArray,
  136.         numberOfAttributes)
  137. Prs2EStateInfo prs2EStateInfo;
  138. Relation explainRelation;
  139. Relation relation;
  140. AttributeNumber attributeNumber;
  141. int oldOrNewTuple;
  142. ObjectId oldTupleOid;
  143. AttributeValues oldAttributeValues;
  144. RuleLock oldTupleLocks;
  145. Prs2LockType oldTupleLockType;
  146. ObjectId newTupleOid;
  147. AttributeValues newAttributeValues;
  148. RuleLock newTupleLocks;
  149. Prs2LockType newTupleLockType;
  150. AttributeNumberPtr attributeArray;
  151. AttributeNumber numberOfAttributes;
  152. {
  153.     Prs2OneLock oneLock;
  154.     int nlocks;
  155.     int i;
  156.     int finalStatus;
  157.     LispValue plan;
  158.     LispValue ruleInfo;
  159.     LispValue planQual;
  160.     LispValue planAction;
  161.     ParamListInfo paramList;
  162.     AttributeNumber lockAttrNo;
  163.     AttributeValues attributeValues;
  164.     Prs2LockType lockType;
  165.     ObjectId ruleId;
  166.     ObjectId tupleOid;
  167.     RuleLock locks;
  168.     Prs2LockType lockTypeToBeUsed;
  169.     AttributeNumber eventAttr;
  170.     AttributeNumber a;
  171.     Boolean changed;
  172.  
  173.  
  174.     if (oldOrNewTuple == PRS2_OLD_TUPLE) {
  175.     if (oldAttributeValues == NULL) {
  176.         elog(WARN,"prs2ActivateBackwardChainingRules: Internal error");
  177.     }
  178.     attributeValues = oldAttributeValues;
  179.     lockTypeToBeUsed = oldTupleLockType;
  180.     locks = oldTupleLocks;
  181.     tupleOid = oldTupleOid;
  182.     } else if (oldOrNewTuple == PRS2_NEW_TUPLE) {
  183.     if (newAttributeValues == NULL) {
  184.         elog(WARN,"prs2ActivateBackwardChainingRules: Internal error");
  185.     }
  186.     attributeValues = newAttributeValues;
  187.     lockTypeToBeUsed = newTupleLockType;
  188.     locks = newTupleLocks;
  189.     tupleOid = newTupleOid;
  190.     } else {
  191.     elog(WARN,
  192.     "prs2ActivateBackwardChainingRules: illegal tuple spec:%d",
  193.     oldOrNewTuple);
  194.     }
  195.     
  196.     if (attributeValues[attributeNumber-1].isCalculated) {
  197.     /*
  198.      * we have already calculated the value for this attribute.
  199.      * Do nothing...
  200.      */
  201.     return;
  202.     }
  203.  
  204.     nlocks = prs2GetNumberOfLocks(locks);
  205.     for (i=0; i<nlocks ; i++) {
  206.     oneLock = prs2GetOneLockFromLocks(locks, i);
  207.     lockType = prs2OneLockGetLockType(oneLock);
  208.     lockAttrNo = prs2OneLockGetAttributeNumber(oneLock);
  209.     ruleId = prs2OneLockGetRuleId(oneLock);
  210.         if (lockType==lockTypeToBeUsed&& attributeNumber==lockAttrNo) {
  211.         /*
  212.          * We've found a 'LockTypeXXXWrite' lock, i.e. there
  213.          * is a rule that might calculate a new value
  214.          * for this attribute.
  215.          *
  216.          * Check for loops!
  217.          */
  218.         if (prs2RuleStackSearch(prs2EStateInfo,
  219.                 ruleId, tupleOid, attributeNumber)) {
  220.         /*
  221.          * Ooops! a rule loop was found.
  222.          * Currently we decide to ignore the rule.
  223.          */
  224.         continue;    /* the for loop... */
  225.         }
  226.         /*
  227.          * now add the stack (loop detection) info...
  228.          */
  229.         prs2RuleStackPush(prs2EStateInfo,
  230.                 ruleId, tupleOid, attributeNumber);
  231.         /*
  232.          * Go in the system catalogs and extract the
  233.          * appropriate plan info...
  234.          */
  235.         plan = prs2GetRulePlanFromCatalog(
  236.                 ruleId,
  237.                 prs2OneLockGetPlanNumber(oneLock),
  238.                 ¶mList);
  239.         if (null(plan)) {
  240.         /*
  241.          * No such plan has been found (an obsolete rule?)
  242.          * Continue with the next lock...
  243.          */
  244.         prs2RuleStackPop(prs2EStateInfo);
  245.         continue;
  246.         }
  247.         ruleInfo = prs2GetRuleInfoFromActionPlan(plan);
  248.         planQual = prs2GetQualFromActionPlan(plan);
  249.         planAction = prs2GetActionsFromActionPlan(plan);
  250.  
  251.         /*
  252.          * in the case of a rule of the form:
  253.          * ON REPLACE TO REL.Y THEN DO REPLACE NEW(X=...)
  254.          * activate this rule only if the attribute 'Y' has been
  255.          * replaced by either the user or another ON REPLACE rule.
  256.          */
  257.         if (lockType==LockTypeReplaceWrite
  258.         && oldOrNewTuple == PRS2_NEW_TUPLE) {
  259.         eventAttr = prs2GetEventAttributeNumberFromRuleInfo(ruleInfo);
  260.         /*
  261.          * try to calculate this attribute, in order to see if
  262.          * it is calculated by another rule
  263.          */
  264.         prs2ActivateBackwardChainingRules(
  265.                 prs2EStateInfo,
  266.                 explainRelation,
  267.                 relation,
  268.                 eventAttr,
  269.                 PRS2_NEW_TUPLE,
  270.                 oldTupleOid,
  271.                 oldAttributeValues,
  272.                 oldTupleLocks,
  273.                 oldTupleLockType,
  274.                 newTupleOid,
  275.                 newAttributeValues,
  276.                 newTupleLocks,
  277.                 newTupleLockType,
  278.                 attributeArray,
  279.                 numberOfAttributes);
  280.         /*
  281.          * Now check if this attribute has been updated by
  282.          * another rule (in which case its 'isChanged' field
  283.          * would be True) or by the user (in which case this
  284.          * attribute must be among the attributes of the 
  285.          * 'attributeArray'
  286.          */
  287.         changed = (Boolean) 0;
  288.         if (numberOfAttributes == 0) {
  289.             /*
  290.              * that means 'all the attributes of the tuple'
  291.              */
  292.             changed = (Boolean) 1;
  293.         }
  294.         for (a=0; a<numberOfAttributes; a++) {
  295.             if (attributeArray[a] == eventAttr) {
  296.             changed = (Boolean) 1;
  297.             break;
  298.             }
  299.         }
  300.         if (attributeValues[eventAttr-1].isChanged)
  301.             changed = (Boolean) 1;
  302.         if (!changed) {
  303.             /*
  304.              * this attribute has not been updated by the user
  305.              * or by another `on replace' rule.
  306.              * So the current rule does not
  307.              * apply, and we have to ignore it.
  308.              */
  309.             continue;    /* the for loop... */
  310.         }
  311.         }
  312.         /*
  313.          * Now try to calculate all the parameters needed to fill in
  314.          * the plan
  315.          */
  316.         prs2CalculateAttributesOfParamNodes(
  317.             prs2EStateInfo,
  318.             explainRelation,
  319.             relation,
  320.             paramList,
  321.             oldTupleOid,
  322.             oldAttributeValues,
  323.             oldTupleLocks,
  324.             oldTupleLockType,
  325.             newTupleOid,
  326.             newAttributeValues,
  327.             newTupleLocks,
  328.             newTupleLockType,
  329.             attributeArray,
  330.             numberOfAttributes);
  331.         Prs2Stats_rulesTested +=1;    /* update statistics */
  332.         if (prs2CheckQual(planQual, paramList, prs2EStateInfo)) {
  333.         Prs2Stats_rulesActivated +=1;    /* update statistics */
  334.         /*
  335.          * the qualification is true. Execute the action
  336.          * part in order to caclulate the new value
  337.          * for the attribute...
  338.          *
  339.          * Note that 'actionPlan' must only contain one
  340.          * item!
  341.          */
  342.         if (null(planAction)) {
  343.             /*
  344.              * then this is a
  345.              * ON RETRIEVE TO ... DO INSTEAD NOTHING
  346.              * rule.
  347.              */
  348.             attributeValues[attributeNumber-1].isCalculated= (Boolean)1;
  349.             attributeValues[attributeNumber-1].isChanged= (Boolean)1;
  350.             attributeValues[attributeNumber-1].isNull= (Boolean)1;
  351.         } else {
  352.             if (CDR(planAction) != LispNil) {
  353.             elog(WARN, "planAction has more than 1 items!");
  354.             }
  355.             /*
  356.              * this is NOT a null action
  357.              */
  358.             if (prs2RunOnePlanAndGetValue(CAR(planAction),
  359.                 paramList,
  360.                 prs2EStateInfo,
  361.                 &(attributeValues[attributeNumber-1].value),
  362.                 &(attributeValues[attributeNumber-1].isNull))) {
  363.             /*
  364.              * A value was calculated by the rule. 
  365.              * Store it in the 'attributeValues' array.
  366.              */
  367.             attributeValues[attributeNumber-1].isCalculated=
  368.                                 (Boolean)1;
  369.             attributeValues[attributeNumber-1].isChanged=
  370.                                 (Boolean)1;
  371.             if (explainRelation != NULL) {
  372.             storeExplainInfo(explainRelation,
  373.                     ruleId,
  374.                     relation,
  375.                     tupleOid);
  376.             }
  377.         }/*else*/
  378.         }
  379.         /*
  380.          * OK, now pop the rule stack information
  381.          */
  382.         prs2RuleStackPop(prs2EStateInfo);
  383.         }
  384.     }
  385.     }/*for*/
  386.  
  387.     if (!attributeValues[attributeNumber-1].isCalculated) {
  388.     /*
  389.      * no rule was applicable. Use the value stored in the tuple
  390.      * (NOTE: this value has already been stored in the attributeValues,
  391.      * (when the 'attributeValues' array was first created)
  392.      * so we only need to change the flags.
  393.      */
  394.     attributeValues[attributeNumber-1].isCalculated = (Boolean)1;
  395.     attributeValues[attributeNumber-1].isChanged = (Boolean)0;
  396.     }
  397.  
  398.     return;
  399.  
  400. }
  401.  
  402. /*----------------------------------------------------------------------
  403.  *
  404.  * prs2CalculateAttributesOfParamNodes
  405.  *
  406.  */
  407.  
  408. void
  409. prs2CalculateAttributesOfParamNodes(
  410.         prs2EStateInfo,
  411.         explainRelation,
  412.         relation,
  413.         paramList,
  414.         oldTupleOid,
  415.         oldTupleAttributeValues,
  416.         oldTupleRuleLock,
  417.         oldTupleLockType,
  418.         newTupleOid,
  419.         newTupleAttributeValues,
  420.         newTupleRuleLock,
  421.         newTupleLockType,
  422.         attributeArray,
  423.         numberOfAttributes)
  424. Prs2EStateInfo prs2EStateInfo;
  425. Relation explainRelation;
  426. Relation relation;
  427. ParamListInfo paramList;
  428. ObjectId oldTupleOid;
  429. AttributeValues oldTupleAttributeValues;
  430. RuleLock oldTupleRuleLock;
  431. Prs2LockType oldTupleLockType;
  432. ObjectId newTupleOid;
  433. AttributeValues newTupleAttributeValues;
  434. RuleLock newTupleRuleLock;
  435. Prs2LockType newTupleLockType;
  436. AttributeNumberPtr attributeArray;
  437. AttributeNumber numberOfAttributes;
  438. {
  439.  
  440.     Name attributeName;
  441.     AttributeNumber attributeNumber;
  442.     LispValue attributesNeededInPlan;
  443.     LispValue lispAttributeName;
  444.     int i;
  445.     Boolean isNull;
  446.  
  447.     if (paramList == NULL) {
  448.     return;
  449.     }
  450.  
  451.     i = 0;
  452.     while (paramList[i].kind != PARAM_INVALID) {
  453.     attributeName = paramList[i].name;
  454.     attributeNumber = paramList[i].id;
  455.     if (paramList[i].kind == PARAM_OLD) {
  456.         /*
  457.          * make sure that the value stored in the old tuple
  458.          * is the correct one
  459.          */
  460.         prs2ActivateBackwardChainingRules(
  461.             prs2EStateInfo,
  462.             explainRelation,
  463.             relation,
  464.             attributeNumber,
  465.             PRS2_OLD_TUPLE,
  466.             oldTupleOid,
  467.             oldTupleAttributeValues,
  468.             oldTupleRuleLock,
  469.             oldTupleLockType,
  470.             newTupleOid,
  471.             newTupleAttributeValues,
  472.             newTupleRuleLock,
  473.             newTupleLockType,
  474.             attributeArray,
  475.             numberOfAttributes);
  476.         /*
  477.          * Find and store the value for this parameter.
  478.          */
  479.         if (attributeNumber > 0 ) {
  480.         paramList[i].value =
  481.                 oldTupleAttributeValues[attributeNumber-1].value;
  482.         if (oldTupleAttributeValues[attributeNumber-1].isNull)
  483.             paramList[i].isnull = true;
  484.         else
  485.             paramList[i].isnull = false;
  486.         } else {
  487.         if (attributeNumber == ObjectIdAttributeNumber){
  488.             paramList[i].value = ObjectIdGetDatum(oldTupleOid);
  489.         } else {
  490.             elog(WARN,
  491.             "Sorry,no system attributes (except oid) allowed in rules");
  492.         }
  493.         }
  494.     } else if (paramList[i].kind == PARAM_NEW) {
  495.         /*
  496.          * make sure that the value stored in the new tuple
  497.          * is the correct one
  498.          */
  499.         prs2ActivateBackwardChainingRules(
  500.             prs2EStateInfo,
  501.             explainRelation,
  502.             relation,
  503.             attributeNumber,
  504.             PRS2_NEW_TUPLE,
  505.             oldTupleOid,
  506.             oldTupleAttributeValues,
  507.             oldTupleRuleLock,
  508.             oldTupleLockType,
  509.             newTupleOid,
  510.             newTupleAttributeValues,
  511.             newTupleRuleLock,
  512.             newTupleLockType,
  513.             attributeArray,
  514.             numberOfAttributes);
  515.         /*
  516.          * store information about this attribute (type, value etc)
  517.          * in the paramList
  518.          */
  519.         paramList[i].type = get_atttype(relation->rd_id, attributeNumber);
  520.         paramList[i].length = (Size) get_typlen(paramList[i].type);
  521.         if (attributeNumber > 0) {
  522.         paramList[i].value =
  523.                 newTupleAttributeValues[attributeNumber-1].value;
  524.         if (newTupleAttributeValues[attributeNumber-1].isNull)
  525.             paramList[i].isnull = true;
  526.         else
  527.             paramList[i].isnull = false;
  528.         } else {
  529.         if (attributeNumber == ObjectIdAttributeNumber){
  530.             paramList[i].value = ObjectIdGetDatum(newTupleOid);
  531.         } else {
  532.             elog(WARN,
  533.             "Sorry,no system attributes (except oid) allowed in rules");
  534.         }
  535.         }
  536.     } else {
  537.         elog(WARN,"Illegal param kind = (%d), name = %s",
  538.         paramList[i].kind, paramList[i].name);
  539.     }
  540.     /*
  541.      * Continue with the next parameter
  542.      */
  543.     i += 1;
  544.     } /*while*/
  545. }
  546.  
  547. /*-----------------------------------------------------------------------
  548.  * prs2ActivateForwardChainingRules
  549.  */
  550. void
  551. prs2ActivateForwardChainingRules(
  552.         prs2EStateInfo,
  553.         explainRelation,
  554.         relation,
  555.         attributeNumber,
  556.         actionLockType,
  557.         oldOrNewTuple,
  558.         oldTupleOid,
  559.         oldAttributeValues,
  560.         oldTupleLocks,
  561.         oldTupleLockType,
  562.         newTupleOid,
  563.         newAttributeValues,
  564.         newTupleLocks,
  565.         newTupleLockType,
  566.         insteadRuleFoundP,
  567.         attributeArray,
  568.         numberOfAttributes)
  569. Prs2EStateInfo prs2EStateInfo;
  570. Relation explainRelation;
  571. Relation relation;
  572. AttributeNumber attributeNumber;
  573. int oldOrNewTuple;
  574. Prs2LockType actionLockType;
  575. ObjectId oldTupleOid;
  576. AttributeValues oldAttributeValues;
  577. RuleLock oldTupleLocks;
  578. Prs2LockType oldTupleLockType;
  579. ObjectId newTupleOid;
  580. AttributeValues newAttributeValues;
  581. RuleLock newTupleLocks;
  582. Prs2LockType newTupleLockType;
  583. bool *insteadRuleFoundP;
  584. AttributeNumberPtr attributeArray;
  585. AttributeNumber numberOfAttributes;
  586. {
  587.     Prs2OneLock oneLock;
  588.     int nlocks;
  589.     int i;
  590.     int finalStatus;
  591.     LispValue plan;
  592.     LispValue ruleInfo;
  593.     LispValue planQual;
  594.     LispValue planActions;
  595.     ParamListInfo paramList;
  596.     AttributeNumber lockAttrNo;
  597.     Prs2LockType lockType;
  598.     ObjectId ruleId;
  599.     RuleLock locks;
  600.     AttributeValues attributeValues;
  601.     ObjectId tupleOid;
  602.  
  603.     /*
  604.      * Have we encountered an 'instead' rule ???
  605.      */
  606.     *insteadRuleFoundP = false;
  607.  
  608.     if (oldOrNewTuple == PRS2_OLD_TUPLE) {
  609.     attributeValues = oldAttributeValues;
  610.     locks = oldTupleLocks;
  611.     tupleOid = oldTupleOid;
  612.     } else if (oldOrNewTuple == PRS2_NEW_TUPLE) {
  613.     attributeValues = newAttributeValues;
  614.     locks = newTupleLocks;
  615.     tupleOid = newTupleOid;
  616.     } else {
  617.     elog(WARN,
  618.     "prs2ActivateForwardChainingRules: illegal tuple spec:%d",
  619.     oldOrNewTuple);
  620.     }
  621.     
  622.     nlocks = prs2GetNumberOfLocks(locks);
  623.     for (i=0; i<nlocks ; i++) {
  624.     oneLock = prs2GetOneLockFromLocks(locks, i);
  625.     lockType = prs2OneLockGetLockType(oneLock);
  626.     lockAttrNo = prs2OneLockGetAttributeNumber(oneLock);
  627.     ruleId = prs2OneLockGetRuleId(oneLock);
  628.         if (lockType==actionLockType && attributeNumber==lockAttrNo) {
  629.         /*
  630.          * We've found a 'LockTypeXXXAction' lock, i.e. there
  631.          * is a rule that might be activated by this event.
  632.          * for this attribute.
  633.          *
  634.          * Go in the system catalogs and extract the
  635.          * appropriate plan info...
  636.          */
  637.         plan = prs2GetRulePlanFromCatalog(
  638.                 ruleId,
  639.                 prs2OneLockGetPlanNumber(oneLock),
  640.                 ¶mList);
  641.         if (null(plan)) {
  642.         /*
  643.          * No such plan has been found (an obsolete rule?)
  644.          * Continue with the next lock...
  645.          */
  646.         continue;
  647.         }
  648.         ruleInfo = prs2GetRuleInfoFromActionPlan(plan);
  649.         planQual = prs2GetQualFromActionPlan(plan);
  650.         planActions = prs2GetActionsFromActionPlan(plan);
  651.  
  652.         /*
  653.          * Now try to calculate all the parameters needed to fill in
  654.          * the plan
  655.          */
  656.         prs2CalculateAttributesOfParamNodes(
  657.             prs2EStateInfo,
  658.             explainRelation,
  659.             relation,
  660.             paramList,
  661.             oldTupleOid,
  662.             oldAttributeValues,
  663.             oldTupleLocks,
  664.             oldTupleLockType,
  665.             newTupleOid,
  666.             newAttributeValues,
  667.             newTupleLocks,
  668.             newTupleLockType,
  669.             attributeArray,
  670.             numberOfAttributes);
  671.         Prs2Stats_rulesTested +=1;    /* update statistics */
  672.         if (prs2CheckQual(planQual, paramList, prs2EStateInfo)) {
  673.         /*
  674.          * the qualification is true. Execute the action
  675.          * part of the rule.
  676.          */
  677.         Prs2Stats_rulesActivated +=1;    /* update statistics */
  678.         prs2RunActionPlans(planActions, paramList, prs2EStateInfo);
  679.         if (prs2IsRuleInsteadFromRuleInfo(ruleInfo)) {
  680.             *insteadRuleFoundP = true;
  681.         }
  682.         if (explainRelation != NULL) {
  683.             storeExplainInfo(explainRelation,
  684.                     ruleId,
  685.                     relation,
  686.                     tupleOid);
  687.         }
  688.         }
  689.     }
  690.     }/*for*/
  691. }
  692.